<!-- 文件预览组件 -->
<template>
  <el-dialog v-model="visible" title="文件预览" :draggable="true" :width="dialogWidth" @close="handleClose">
    <!-- 加载状态 -->
    <el-loading v-if="loading" fullscreen text="加载中..."></el-loading>

    <!-- 图片预览 -->
    <el-image v-if="fileType === 'image'" :src="fileUrl" fit="contain" preview-teleported></el-image>

    <!-- PDF预览（使用iframe或pdf.js） -->
    <iframe v-if="fileType === 'pdf'" :src="fileUrl" frameborder="0" width="100%" :height="dialogHeight"></iframe>

    <!-- 视频预览 -->
    <video v-if="fileType === 'video'" :src="fileUrl" controls width="100%" :height="dialogHeight"></video>

    <!-- 音频预览 -->
    <audio v-if="fileType === 'audio'" :src="fileUrl" controls width="100%"></audio>

    <!-- 文本文件预览 -->
    <pre v-if="fileType === 'text'" class="text-pre">{{ textContent }}</pre>

    <!-- Office文件（需后端转换为PDF，或用第三方库） -->
    <div v-if="fileType === 'office'">
      <iframe :src="fileUrl" frameborder="0" width="100%" :height="dialogHeight"></iframe>
    </div>

    <!-- 不支持的类型 -->
    <div v-if="fileType === 'unknown'">
      <el-alert type="warning" message="不支持的文件类型" />
      <el-button @click="downloadFile">下载文件</el-button>
    </div>
  </el-dialog>
</template>

<script setup>
import { ref, watch, computed } from 'vue';
import { ElMessage, ElLoading } from 'element-plus';
import request from '@/api/request'

// 接收父组件参数
const props = defineProps({
  // 是否显示预览框
  show: {
    type: Boolean,
    default: false
  },
  // 文件信息（包含bucketName、objectName、fileName）
  fileInfo: {
    type: Object,
    required: true
  }
});

// 内部状态
const visible = ref(false);
const loading = ref(false);
const fileUrl = ref('');
const textContent = ref('');
const fileType = ref('unknown');

// 对话框尺寸
const dialogWidth = computed(() => {
  return fileType.value === 'image' ? '80%' : '90%';
});
const dialogHeight = computed(() => {
  return window.innerHeight - 200 + 'px'; // 动态计算高度
});

// 监听显示状态
watch(() => props.show, (val) => {
  visible.value = val;
  if (val) {
    loadFilePreview(); // 显示时加载文件
  }
});

// 加载文件预览
const loadFilePreview = async () => {
  const { bucketName, objectName, fileName } = props.fileInfo;
  loading.value = true;
  try {
    // 1. 调用后端接口获取预签名URL
    const res = await request.get("minioFile/preview", {
      params: { bucketName, objectName }
    });
    fileUrl.value = res.data;
    // 2. 判断文件类型
    const ext = fileName.split('.').pop()?.toLowerCase();
    if (['jpg', 'jpeg', 'png', 'gif', 'bmp'].includes(ext)) {
      fileType.value = 'image';
    } else if (ext === 'pdf') {
      fileType.value = 'pdf';
    } else if (['mp4', 'webm', 'mov'].includes(ext)) {
      fileType.value = 'video';
    } else if (['mp3', 'wav', 'ogg'].includes(ext)) {
      fileType.value = 'audio';
    } else if (['txt', 'md', 'json', 'js', 'css', 'html'].includes(ext)) {
      fileType.value = 'text';
      // 加载文本内容
      const textRes = await request.get(fileUrl.value);
      textContent.value = textRes.data;
    } else if (['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'].includes(ext)) {
      fileType.value = 'office';

      // 1. Base64编码（用之前验证过的正确编码函数）
      const base64Str = base64Encode(fileUrl.value);
      // 2. 对Base64结果二次URL编码（处理+、/等特殊字符）
      const encodedBase64 = encodeURIComponent(base64Str);
      // 3. 拼接kkFileView地址（使用urlBase64参数）
      const previewUrl = `${import.meta.env.VITE_PREVIEW_URL}${encodedBase64}`;

      fileUrl.value = previewUrl
    } else {
      fileType.value = 'unknown';
    }
  } catch (err) {
    ElMessage.error('预览失败：' + (err.response?.data?.msg || '网络错误'));
  } finally {
    loading.value = false;
  }
};
// 1. 实现 UTF-8 编码的 Base64 工具函数（解决中文/特殊字符问题）
const base64Encode = (str) => {
  // 先将字符串转为 UTF-8 字节数组
  const utf8Bytes = new TextEncoder().encode(str);
  // 再将字节数组转为 Base64 字符串
  return btoa(String.fromCharCode(...utf8Bytes));
};
// 关闭预览
const handleClose = () => {
  emits('update:show', false);
  // 重置状态
  fileUrl.value = '';
  textContent.value = '';
  fileType.value = 'unknown';
};

// 下载文件
const downloadFile = () => {
  const a = document.createElement('a');
  a.href = fileUrl.value;
  a.download = props.fileInfo.fileName;
  a.click();
};

// 向父组件传递事件
const emits = defineEmits(['update:show']);
</script>

<style scoped>
.text-pre {
  max-height: 600px;
  overflow: auto;
  padding: 16px;
  background: #f5f5f5;
  border-radius: 4px;
}
</style>